package edu.trinity.cs.cjenkin1.webcrawler;

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Choice;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Label;
import java.awt.List;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Vector;

import org.htmlparser.Node;
import org.htmlparser.Parser;
import org.htmlparser.tags.ImageTag;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;

public class WebCrawler extends Applet implements ActionListener, Runnable {

	private static final long serialVersionUID = 1L;
	public static final String SEARCH = "Search";
    public static final String STOP = "Stop";
    public static final String DISALLOW = "Disallow:";
    public static final int    SEARCH_LIMIT = 50;
	
	Panel mainPanel;
	List listMatches;
	Label labelStatus;
	
    // URLs to be searched
    Vector<String> vectorToSearch;
    // URLs already searched
    Vector<String> vectorSearched;
    // URLs which match
    Vector<String> vectorMatches;
	
    Thread searchThread;

    TextField textURL;
    Choice    choiceType;
    
	public static void main(String[] args) {
        Frame f = new Frame("WebFrame");
        WebCrawler applet = new WebCrawler();
        f.add("Center", applet);

/*		Behind a firewall set your proxy and port here!
*//*
        Properties props= new Properties(System.getProperties());
        props.put("http.proxySet", "true");
	props.put("http.proxyHost", "webcache-cup");
	props.put("http.proxyPort", "8080");

        Properties newprops = new Properties(props);
        System.setProperties(newprops);
*/
        applet.init();
        applet.start();
        f.pack();
        f.setVisible(true);
	}
	
	public void pain(Graphics g) {
      	//Draw a Rectangle around the applet's display area.
      	g.drawRect(0, 0, getSize().width - 1, getSize().height - 1);

      	mainPanel.paint(g);
      	mainPanel.paintComponents(g);
	}
	
	public void init() {
		// set up the main UI panel
		mainPanel = new Panel();
		mainPanel.setLayout(new BorderLayout(5, 5));

		// text entry components
		Panel panelEntry = new Panel();
		panelEntry.setLayout(new BorderLayout(5, 5));

		Panel panelURL = new Panel();
		panelURL.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5));
		Label labelURL = new Label("Starting URL: ", Label.RIGHT);
		panelURL.add(labelURL);
		textURL = new TextField("", 40);
		panelURL.add(textURL);
		panelEntry.add("North", panelURL);

		Panel panelType = new Panel();
		panelType.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5));
		Label labelType = new Label("Content type: ", Label.RIGHT);
		panelType.add(labelType);
		choiceType = new Choice();
		choiceType.addItem("text/html");
		choiceType.addItem("audio/basic");
		choiceType.addItem("audio/au");
		choiceType.addItem("audio/aiff");
		choiceType.addItem("audio/wav");
		choiceType.addItem("video/mpeg");
		choiceType.addItem("video/x-avi");
		//added types
		choiceType.addItem("image/jpeg");
		choiceType.addItem("image/png");
		choiceType.addItem("image/jpg");
		panelType.add(choiceType);
		panelEntry.add("South", panelType);

		mainPanel.add("North", panelEntry);

		// list of result URLs
		Panel panelListButtons = new Panel();
		panelListButtons.setLayout(new BorderLayout(5, 5));

		Panel panelList = new Panel();
		panelList.setLayout(new BorderLayout(5, 5));
		Label labelResults = new Label("Search results");
		panelList.add("North", labelResults);
		Panel panelListCurrent = new Panel();
		panelListCurrent.setLayout(new BorderLayout(5, 5));
		listMatches = new List(10);
		panelListCurrent.add("North", listMatches);
		labelStatus = new Label("");
		panelListCurrent.add("South", labelStatus);
		panelList.add("South", panelListCurrent);

		panelListButtons.add("North", panelList);

		// control buttons
		Panel panelButtons = new Panel();
		Button buttonSearch = new Button(SEARCH);
		buttonSearch.addActionListener(this);
		panelButtons.add(buttonSearch);
		Button buttonStop = new Button(STOP);
		buttonStop.addActionListener(this);
		panelButtons.add(buttonStop);

		panelListButtons.add("South", panelButtons);

		mainPanel.add("South", panelListButtons);

		add(mainPanel);
		setVisible(true);

		repaint(); 

		// initialize search data structures
		vectorToSearch = new Vector<String>();
		vectorSearched = new Vector<String>();
		vectorMatches = new Vector<String>();

		// set default for URL access
		URLConnection.setDefaultAllowUserInteraction(false);
	}
	
	public void actionPerformed(ActionEvent event) {
		String command = event.getActionCommand();

		if (command.compareTo(SEARCH) == 0) {
		    setStatus("searching...");

		    // launch a thread to do the search
		    if (searchThread == null) {
			searchThread = new Thread(this);
		    }
		    searchThread.start();
		}
		else if (command.compareTo(STOP) == 0) {
		    stop();
		}
	}


    public void stop() {
    	if (searchThread != null) {
    	    setStatus("stopping...");
    	    searchThread = null;
    	}
    }
	
	public void run() {
		String strURL = textURL.getText();
		String strTargetType = choiceType.getSelectedItem();
		int numberSearched = 0;
		int numberFound = 0;

		if (strURL.length() == 0) {
		    setStatus("ERROR: must enter a starting URL");
		    return;
		}
		
		// initialize search data structures
		vectorToSearch.removeAllElements();
		vectorSearched.removeAllElements();
		vectorMatches.removeAllElements();
		listMatches.removeAll();

		vectorToSearch.addElement(strURL);
		
		while (!vectorToSearch.isEmpty() && 
			Thread.currentThread() == searchThread) {
			
		    strURL = (String) vectorToSearch.elementAt(0);
	    	vectorToSearch.remove(0);
		    setStatus("searching " + strURL);
		    
		    URL url;
		    try { 
		    	url = new URL(strURL);
		    } catch (MalformedURLException e) {
		    	setStatus("ERROR: invalid URL " + strURL);
		    	continue;
		    }
		    
		    vectorSearched.add(strURL);
		    
		    if (!url.getProtocol().equals("http") ) {
		    	setStatus("Non-http protocols not supported");
		    	continue;
		    }
		    
		    try {
		    	URLConnection urlc = url.openConnection();
		    	Parser urlParser = new Parser(urlc);
		    	
		    	//TODO here
		    	NodeList matchingNodes = 
		    		urlParser.extractAllNodesThatMatch(
		    		ImageNodeFilter.i.or(LinkNodeFilter.i));
		    	
		    	for(Node node : new NodeIterator2(matchingNodes.elements())) {
		    		if (node instanceof LinkTag) {
		    			vectorToSearch.add(((LinkTag) node).getLink() );
		    		}
		    		else if(node instanceof ImageTag) {
		    			vectorMatches.add(((ImageTag) node).getImageURL() );
		    		}
		    	}
		    	
		    } catch (IOException e) {
				setStatus("ERROR: couldn't open URL " + strURL);
				continue;
		    }
		    catch (ParserException e) {
		    	setStatus(e.toString());
		    }
		    //have not done limit links, filter, etc
		}
	}
	
    void setStatus(String status) {
    	labelStatus.setText(status);
    }
}